package gnss

import (
	"dgo/goutils/gis"
	"dgo/goutils/utils"
	"fmt"
	"time"
)

/***
 分析RTCM数据做展示
ana := gnssutils.NewGnssRtcmAnalyzer("test")
ana.InputBuf(rtcmBuf)
*/

type GnssRtcmAnalyzer struct {
	Id             string
	StartT         time.Time
	LatestMsmT     time.Time
	LatestMsm      *RtcmRawMsmObs
	rtcmRaw        *Rtcm3RawBuf
	DelayCheckFlag int
	OnRtcmErr      func(msg string)
	OnPrint        func(msgid uint16, tow uint32, tag int, info string) bool
	OnFilter       func(msgid uint16, tow uint32) bool
}

func (this *GnssRtcmAnalyzer) doPrint(msgid uint16, tow uint32, tag int, s string, args ...interface{}) {
	str := fmt.Sprintf(s, args...)
	if this.OnPrint != nil {
		if !this.OnPrint(msgid, tow, tag, str) {
			return
		}
	}
	utils.Log.InfoTypef(this.Id, "%s", str)
}

func NewGnssRtcmAnalyzer(id string) *GnssRtcmAnalyzer {
	rval := &GnssRtcmAnalyzer{
		DelayCheckFlag: 1,
		rtcmRaw:        NewRtcm32RawBuf(id),
	}
	rval.rtcmRaw.OnErr = func(errcode int, err error) bool {
		if rval.OnRtcmErr != nil {
			rval.OnRtcmErr(fmt.Sprintf("[%d]RTCM ERR:%s", GetRtcmMsgId(rval.rtcmRaw.buf, 24), err.Error()))
		} else {
			utils.Log.ErrTypef(id, "[%d]RTCM ERR:%s", GetRtcmMsgId(rval.rtcmRaw.buf, 24), err.Error())
		}
		return true
	}
	tow := uint32(0)
	rval.rtcmRaw.OnRtcmBuf = func(rtcmBuf []byte) {
		msgid := uint16(GetRtcmMsgId(rtcmBuf, 24))
		if msgid == 1005 || msgid == 1006 {
			rec := &GnssStation{}
			DecodeRtcm1005V1(rec, rtcmBuf, 24)
			vb, vl, vh := gis.Ecef2Pos(rec.Pos[0], rec.Pos[1], rec.Pos[2])
			vlng := gis.R2D(vl)
			vlat := gis.R2D(vb)

			refT := rval.StartT
			if refT.IsZero() {
				refT = time.Now().UTC()
			}
			t1 := TOW2Time(refT, uint(tow))
			rval.doPrint(msgid, tow, 0, "[%s]msgid:%d, t:%s, itrf:%d, vrs-satid:%d, NaviIndicatorText:%s, Oscillator:%d, x, y, z:%.6f, %.6f, %.6f, lng:%.6f, lat:%.6f, height:%.6f",
				id, msgid, utils.DateTimeString2(t1), rec.Itrf, rec.StationId, rec.NaviIndicatorText(), rec.OscillatorIndicator, rec.Pos[0], rec.Pos[1], rec.Pos[2], vlng, vlat, vh)
			rval.doPrint(msgid, tow, 1, "[%s]raw:%s", id, utils.BufToHexStr(rtcmBuf, 0, ""))

		} else if msgid == 1033 {
			rec := &Gnss1033Rec{}
			DecodeRtcm1033(rec, rtcmBuf, 24)
			refT := rval.StartT
			if refT.IsZero() {
				refT = time.Now().UTC()
			}
			t1 := TOW2Time(refT, uint(tow))
			rval.doPrint(msgid, tow, 0, "[%s]msgid:%d, t:%s, %s", id, msgid, utils.DateTimeString2(t1), rec.String())
			rval.doPrint(msgid, tow, 1, "[%s]raw:%s", id, utils.BufToHexStr(rtcmBuf, 0, ""))
		} else {
			rawObs := &RtcmRawMsmObs{}
			rval.LatestMsm = rawObs
			var sigmask uint32
			var satmask uint64
			if RtcmIsMsm4(msgid) {
				msm := NewRtcmRawMsm4()
				msm.DecodeMsm(rtcmBuf)
				sigmask = msm.Header.SignalMask
				satmask = msm.Header.SatMask
				tow = msm.Header.GetTOW()
				rawObs.Header.CopyInfoFrom(&msm.Header)
				msm.WriteToObs(rawObs)
			} else if RtcmIsMsm7(msgid) {
				//if msgid == 1077{
				//	msgid = 1077
				//}
				msm := NewRtcmRawMsm7()
				msm.DecodeMsm(rtcmBuf)
				sigmask = msm.Header.SignalMask
				satmask = msm.Header.SatMask
				tow = msm.Header.GetTOW()
				rawObs.Header.CopyInfoFrom(&msm.Header)
				msm.WriteToObs(rawObs)
			} else if RtcmIsMsm5(msgid) {
				msm := NewRtcmRawMsm5()
				msm.DecodeMsm(rtcmBuf)
				sigmask = msm.Header.SignalMask
				satmask = msm.Header.SatMask
				tow = msm.Header.GetTOW()
				rawObs.Header.CopyInfoFrom(&msm.Header)
				msm.WriteToObs(rawObs)
			} else {
				rval.doPrint(msgid, tow, 2, "[%s]不支持的msmtype:%d, sync:%d, raw:%s", id, msgid, rval.rtcmRaw.GetMsmSyncFlag(), utils.BufToHexStr(rtcmBuf, 0, ""))
				return
			}

			refT := rval.StartT
			if refT.IsZero() {
				refT = time.Now().UTC()
			}
			t1 := rawObs.GetMsgTime(refT)
			rval.LatestMsmT = t1
			secs := utils.SecondBetween(t1, time.Now().UTC())
			if rval.StartT.IsZero() {
				if secs > 240 && rval.DelayCheckFlag == 1 {
					rval.doPrint(msgid, tow, 3, "解码异常[时间异常]时间相差%.2f秒, msgid:%d, buf:%s",
						secs, rawObs.Header.MsgID, utils.BufToHexStr(rtcmBuf, 0, " "))
				}
			}
			if rval.DelayCheckFlag == 1 {
				rval.doPrint(msgid, tow, 0, "[%s]msgid:%d, t:%s, between:%.3f", id, rawObs.Header.MsgID, utils.DateTimeString2(t1), secs)
			} else {
				rval.doPrint(msgid, tow, 0, "[%s]msgid:%d, t:%s", id, rawObs.Header.MsgID, utils.DateTimeString2(t1))
			}

			rval.doPrint(msgid, tow, 3, "[%s]%s", id, rawObs.Header.Details())
			rval.doPrint(msgid, tow, 3, "[%s]sig: %s, mask:%X, satmask:%X\r\n", id, PrintRtcmInfoFromMask(rawObs.Header.NaviSys, sigmask), sigmask, satmask)
			rval.doPrint(msgid, tow, 1, "[%s]raw:%s", id, utils.BufToHexStr(rtcmBuf, 0, ""))
			rval.doPrint(msgid, tow, 3, "[%s]details:\n%s", id, rawObs.PrintWithRaw())
		}
	}
	return rval
}

func (this *GnssRtcmAnalyzer) InputBuf(buf []byte) {
	this.rtcmRaw.InputBlockBuf(buf)
}

func (this *GnssRtcmAnalyzer) Reset() {
	this.rtcmRaw.Reset()
}
